#!/bin/bash
# File Name   : start.sh
# Version     : V1.0
# Author      : moshan
# Mail        : mo_shan@yeah.net
# Created Time: 2019-09-17 16:44:16
# Function    : Auto insert data for MySQL.
#########################################################################
work_path=$(pwd)
program_dir=${work_path}/program
log_dir=${work_path}/log
conf_dir=${work_path}/conf
data_dir=${work_path}/data
tty_file=${log_dir}/tty.log
error_file_global=${log_dir}/error.log
error_file_tmp=${log_dir}/error
message_file=${log_dir}/message.log
tmp_file=${log_dir}/tmp.log
pid_tmp_file=${log_dir}/.pid_tmp.log
lock_file=${log_dir}/.lock
value_file=${log_dir}/value.log
tmp_count=${log_dir}/tmp_count.log
length_file=${log_dir}/length.log
data_file=${data_dir}/data_file
conf_file=${conf_dir}/prepare.xml
_conf_file=${conf_dir}/.prepare.xml
conf_file_tmp=${conf_dir}/.prepare.xml.tmp
mysql_info=${conf_dir}/mysql.xml
create_info=${conf_dir}/create.info
_dn_connect_info=${conf_dir}/.dn.info
dn_connect_info=${conf_dir}/dn.info
global_data_is_true=0    #该变量可取的值有:0,1. 验证导入的数据与准备的数据是否一致, 1表示一致
global_single_sharding=0 #该变量可取的值有:0,1
global_multi_sharding=0  #该变量可取的值有:0,1

_version="$(cat /etc/redhat-release | grep CentOS | awk -F 'release' '{print $2}'|awk '{a=$1>=7?7:6;print a}')"

if [ "${_version}x" == "7x" ]
then
    program_file="prepare_data_for_mysql_7"
else
    program_file="prepare_data_for_mysql_6"
fi

delimiter_str=",,,"      #load分隔符

which mysql >/dev/null 2>&1 || {
    echo -e "\n\033[33m[$(date "+%F %H:%M:%S")] 程序运行所需的MySQL环境有误, 请检查环境变量！\n"
    exit 1
    }

[ -d ${data_dir} ] && rm -f ${data_file}_* || mkdir ${data_dir}
[ ! -d ${log_dir} ] && mkdir ${log_dir}
if [ ! -d ${program_dir} -o ! -d ${conf_dir} ]
then
	echo -e "\033[32m[$(date "+%F %H:%M:%S")] 程序运行所需的配置或其他文件不存在！"
	exit
fi
[ -f "/etc/profile" ] && . /etc/profile


function info_connect()
{
    echo "+++++++++++++++++++++++++++++++++++++++++++++++"  
    echo -e "\033[31m${connect_state}\033[0m连接信息如下"
    echo "+++++++++++++++++++++++++++++++++++++++++++++++"  
    echo -e "用户名：\033[31m${info[0]}\033[0m"
    echo -e "密  码：\033[31m${info[1]}\033[0m"
    echo -e "端  口：\033[31m${info[2]}\033[0m"
    echo -e "主  机：\033[31m${info[3]}\033[0m"
    echo "+++++++++++++++++++++++++++++++++++++++++++++++"
}

function update_connect_info()
{
    info_connect #显示连接信息
    echo -e "\033[31m提示：更新时，可以输入e编辑配置文件，也可手动输入，以空格分隔，且正确的信息可用0代替。\033[0m"
    echo -e "\033[31m如,仅密码错误时，可以这样输入：0 new_passwd 0 0\033[0m"
    echo "----------------------------------"
    echo -n "如需更新,请以空格分隔："
    read info[0] info[1] info[2] info[3]
    [ "${info[0]}x" == "ex" ] && vim ${mysql_info} && return
    for ((i=0;i<${#info[*]};i++))
    do
        [ -z ${info[$i]} ] && { break;}
        if [ "${info[$i]}x" == "0x" ]
		then
            info[$i]=`sed -n "s/<\!.*-->//g;s/^.*>\(.*\)<.*/\1/g;$((${i}+1))p" ${mysql_info}`
		fi
        #当输入为0时表示该值不变，即从配置文件中取出来
        row=$(($i+1))
        if [ ${row} -eq 1 ]
        then 
            str=user
        elif [ ${row} -eq 2 ]
        then 
            str=password
        elif [ ${row} -eq 3 ]
        then 
            str=port
        elif [ ${row} -eq 4 ]
        then 
            str=host
        fi
        sed -i "s/<${str}>.*<\/${str}>/<${str}>${info[${i}]}<\/${str}>/g" ${mysql_info};
    done
}

function mysql_connect()
{
    echo "提示:若长时间无反应，可能是该服务器不能连接，请按下CTRL+C重新输入连接信息!"
    flag=1
    while :
    do
        if [ -f "${mysql_info}" ]
        then
            sed -i '5,$d' ${mysql_info}
        else
            touch ${mysql_info}
        fi
        for((i=0;i<4;i++))
        do
            info[$i]=`sed -n "s/<\!.*-->//g;s/.*>\(.*\)<.*/\1/g;$(($i+1))p" ${mysql_info}`
        done
        if [ "${info[0]}x" == "x" -o "${info[1]}x" == "x" -o "${info[2]}x" == "x" -o "${info[3]}x" == "x" ]
        then
            connect_state="本次连接验证失败，"
            update_connect_info
            continue
        fi    
        while :
        do
            while :
            do  
                [ "${info[3]}x" == "localhostx" ] && { break;}
                part=(`echo ${info[3]} | awk -F'.' '{for(i=N+1;i<=NF;i++)print length($i)};'`)
                if [ ${#part[*]} -ne 4 ]
                then
                    connect_state="本次连接验证失败，"
                    info_connect
                    echo -en "连接主机为:${info[3]},格式有误，请重新输入\033[31m主机地址\033[0m："
                    read info[3]
                    sed -i "4s/^.*$/<host>${info[3]}</host>/" ${mysql_info}
                else
		    break
                fi
            done
            for ((i=0;i<${#part[*]};i++))
            do
                [ ! -n "${part[i]}" ] && { flag=0;break;}
                [ "${part[i]}" -ge "4" ] && { flag=0;break;}
                [ "${part[i]}x" == "0x" ] && { flag=0;break;} || { flag=1;}
            done
            if [ ${flag} -eq 0  ]
            then
                connect_state="本次连接验证失败，"
                info_connect
                [ "${info[3]}x" == "localhostx" ] && { break;}
                echo -en "连接主机为:${info[3]},非法主机，请重新输入\033[31m主机地址\033[0m："
                read info[3]
                sed -i "4s/^.*$/<host>${info[3]}</host>/" ${mysql_info}
            else
                break
            fi
        done
        mysql_connect="mysql -u${info[0]} -p${info[1]} -P${info[2]} -h${info[3]} "
        if [ ${flag} -eq 1 ]
        then
            echo "select 1;"|${mysql_connect} >/dev/null 2<&1
            [ $? -eq 0 ] && flag=1 || flag=0
        else
            flag=0
        fi
        if [ ${flag} -eq 0 ]
        then
            connect_state="本次连接验证失败，"
            update_connect_info
            continue
        else 
            connect_state="本次连接验证成功，"
            connet_info_dn=`sed -n "s#<dn count=\(.*\)>#\1#gp" ${conf_file}`
            [ ${connet_info_dn} -ne 1 ] && break
            sed -i "s#<info>.*</info>#<info>${info[0]}:${info[1]}:${info[2]}:${info[3]}</info>#g" ${conf_file}
            break
        fi
    done
}

function get_db_info()
{
    
    echo "----------------------" >${tmp_file}
    echo "show databases;" | ${mysql_connect} >>${tmp_file} 2> /dev/null
    echo "----------------------" >>${tmp_file}
    sed -i '/schema\|mysql\|sys/d;s/Warning:.*$//g;s/Database.*$/服务器现有的数据库/g;2a----------------------' ${tmp_file}
}

function get_table_info()
{
    echo "show columns from ${db_name}.${t_name};"| ${mysql_connect} 2>/dev/null|sed 's/.*uuid_string.*/uuid -4/g;s/.*car_string.*/car -3/g;s/[Ii]dentify[Cc]ode/code -5/g' >>${tmp_file}
    PRI_KEY_NAME="`grep "PRI" ${tmp_file}|grep -v grep|head -1|awk '{print $1}'`"
    if [ -z "${PRI_KEY_NAME}" ]
    then
        PRI_KEY_NAME=`sed -n 2p ${tmp_file}|awk '{print $1}'`
        step=0
        PRI_KEY_ADDR=0
        auto_increment=0
    else
        PRI_KEY_ADDR="`cat -n ${tmp_file}|sed -e 's/[^ ]* //'|grep "PRI"|grep -v grep|awk '{print $1}'|head -1`"
        auto_increment=`cat ${tmp_file}|sed -e 's/[^ ]* //'|grep -i "auto_increment"|grep -v grep|wc -l` 
        if [ ${#PRI_KEY_ADDR} -eq 0 ]
        then
            PRI_KEY_ADDR=0
            step=0
        else
            PRI_KEY_ADDR=$((${PRI_KEY_ADDR}-1))
            step=1
        fi
    fi
    sed -i "s/<addr>\(.*\)<\//<addr>${PRI_KEY_ADDR}<\//g;s/<num>\(.*\)<\//<num>${auto_increment}<\//g;s/<step>\(.*\)<\//<step>${step}<\//g" ${conf_file}
}

function public()
{
    while :
    do
        get_db_info
        for((i=1;i<=`wc -l <${tmp_file}`;i++))
        do
            if [ ${i} -eq `wc -l <${tmp_file}` ]
            then
                sed -n "${i}p" ${tmp_file}
                break
            fi

            if [ ${i} -gt 3 ]
            then
                echo $((${i}-3)).`sed -n "${i}p" ${tmp_file}`
            else
                sed -n "${i}p" ${tmp_file}
            fi
        done
        echo -en "\033[31m输入r返回上一层菜单，请输入库名\033[0m:"
        read db_name
        [ "${db_name}x" == "rx" ] && main_menu
        for ((i=1;i<$((`wc -l <${tmp_file}`-3));i++))
        do
            if [ "${db_name}x" == "${i}x" ]
            then
                db_name=`sed -n "$((${i}+3))p" ${tmp_file}`
                break
            fi
        done
        mark=0
        for name in `cat ${tmp_file}`
        do
            [ "${name}x" == "${db_name}x" ] && mark=$((${mark}+1))
        done
        if [ ${mark} -ne 1 ]
        then
            echo -e "\033[31m输入有误，请重新输入！\033[0m"
            continue
        fi
        while :
        do
            echo "----------------------" >${tmp_file}
            echo "use ${db_name};show tables;" | ${mysql_connect}  >>${tmp_file} 2> /dev/null
            echo "----------------------" >>${tmp_file}
            sed -i  "s/Tables_in_${db_name}/${db_name}库现有的表/g;s/Warning:.*$//g;2a----------------------" ${tmp_file}
            for((i=1;i<=`wc -l <${tmp_file}`;i++))
            do
                [ ${i} -eq `wc -l <${tmp_file}` ] && { sed -n "${i}p" ${tmp_file};break;}
                [ ${i} -gt 3 ] && { echo $((${i}-3)).`sed -n "${i}p" ${tmp_file}`;} || { sed -n "${i}p" ${tmp_file};}
            done
            mark=`cat ${tmp_file}|wc -l`
            if [ ${mark} -eq 3 ]
            then
                echo -e "\033[31m${db_name}库为空！\033[0m请重新选择，或前往服务器建表后重试！"   
                break
            fi
            echo -en "\033[31m输入r返回上一层菜单，请输入表名\033[0m:"
            read t_name
            [ "${t_name}x" == "rx" ] && break
            for ((i=1;i<$((`wc -l <${tmp_file}`-3));i++))
            do
                if [ "${t_name}x" == "${i}x" ]
                then
                    t_name=`sed -n "$((${i}+3))p" ${tmp_file}`
                    echo "您选择了${t_name}表"
                    break
                fi
            done
            mark=0
            for name in `cat ${tmp_file}`
            do
                [ "${name}x" == "${t_name}x" ] && { mark=$((${mark}+1));}
            done
            if [ ${mark} -le 0 ]
            then
                echo -e "\033[31m输入有误，请重新输入！\033[0m"
                continue
            fi
            mark=0
            break
        done
        [ ${mark} -eq 0 ] && { break;}
    done
}

function edit_conf()
{
    row_array=(`sed -n 's#<row max=\(.*\)>\(.*\)</row>.*$#\1 \2#gp' ${conf_file}`)
    [ ${row_array[1]} -le ${row_array[0]} ] && return 
    edit_conf_loop=`echo ${row_array[1]}/${row_array[0]}|bc`
    edit_conf_or_not=$((${row_array[1]}%${row_array[0]}))
    [ "${edit_conf_or_not}x" == "0x" ] && edit_conf_loop=$((${edit_conf_loop}-1))
    dn_row_num=`grep -n "<\/dn>" ${conf_file}|grep -v grep|awk -F: '{print $1}'`
    alg_row_num=`grep -n "<\/algorithm>" ${conf_file}|grep -v grep|awk -F: '{print $1}'`
    grep -Ev "</dn>|</algorithm" ${conf_file} > ${conf_file_tmp}
    for ((i=0;i<${edit_conf_loop};i++))
    do
        row_num=(`grep -n "<info>" ${conf_file}|grep -v grep|awk -F: '{print $1}'`)
        for ((j=0;j<${#row_num[*]};j++))
        do
            edit_conf_tmp=`sed -n "${row_num[$j]}p" ${conf_file}`
            echo "${edit_conf_tmp}" >> ${conf_file_tmp}
        done
        new_row=`echo "${row_array[1]}/((${i}+2))"|bc`
        let new_dn=$i+2
        let new_dn=${new_dn}*${#row_num[*]}
    done
    edit_conf_tmp=`sed -n "${dn_row_num}p" ${conf_file}`    
    echo "${edit_conf_tmp}" >> ${conf_file_tmp}
    edit_conf_tmp=`sed -n "${alg_row_num}p" ${conf_file}`    
    echo "${edit_conf_tmp}" >> ${conf_file_tmp}
    sed -i "s#<row max.*>.*</row>#<row max=${row_array[0]}>${new_row}</row>#g" ${conf_file_tmp}
    sed -i "s#<dn count=.*#<dn count=${new_dn}>#g" ${conf_file_tmp}
    cat ${conf_file_tmp} >${conf_file} #更新配置文件
    [ -f "${conf_file_tmp}" ] && rm -f ${conf_file_tmp}
    global_single_sharding=1
}  

function SendMessage()
{
    kill -9 ${SendMessage_pid} >/dev/null 2<&1
    timeout 10s sh ${program_dir}/SendMessage.sh ${tty_file} ${message_file} & >/dev/null 2<&1
    SendMessage_pid=$!
    vim ${conf_file} +1
}


function check_data_true_sharding()
{
    file_tmp="${1}"
    loop_tmp="${2}"
    echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[35m${loop_tmp}导入完成，下面开始验证数据量是否正确\033[0m"
    count_row="$(wc -l <${file_tmp})"
    count_db_row="$(echo "select count(*) from ${db_name}.${t_name}"|${dn_com} -BN 2>/dev/null)"
    [ ${count_row} -eq ${count_db_row} -a "${count_db_row}x" != "0x" ] && \
    {
        global_data_is_true=1
    }
}

function data_get()
{
    tmp=`cat -n ${conf_file} |grep "<column"|grep -v grep|awk '{print $1}'` #临时变量存放<column></column>标签行号
    global_column=`wc -l <${length_file}` #保存该目标数据表的字段数
    str=`grep "<column" ${conf_file}|grep -v grep|awk -F'>' '{print $1}'` 
    sed -i "/.*length.*/d;s/${str}/<column count=${global_column}/g" ${conf_file} 
    #清除length标签的所有行，替换原配置文件中<column>标签的count属性值
    for ((i=1;i<=${global_column};i++)) #该循环更新column标签的子标签length
    do
        row=$((${tmp}+${i}-1))
        length=`sed -n "${i}p" ${length_file}`
        if [ ${PRI_KEY_ADDR} -eq ${i} ]
        then
            [ ${length} -lt 3 ] && { length=3;}
        fi
        if [ "$(grep -c "," <<< "${length}")x" == "1x" ]
        then
            length_tmp="$(awk -F, '{print $1}' <<< "${length}")"
            length_tmp="$(echo "${#length_tmp}")"
            length="-${length_tmp}$(awk -F, '{print $1$2}' <<< "${length}")"
        fi
        sed -i "${row}a\\    <length col=${i}>${length}</length>" ${conf_file} 
        #向配置文件的column标签的下一行插入length标签
    done
    cat ${conf_file} > ${_conf_file} #备份配置文件
    edit_conf
    echo "----------------------------------"  
    echo -e "\033[31m          温馨提示\033[0m"
    echo "----------------------------------"  
    echo -e "当数据量较大，受网络或机器本身影响\n较大，可能会导致load失败，\n此时程序将会分小块load到各个分片。\n默认阀值是1000w数据量，即当数据量\n超过1000w时，程序自动将其分片！！！\n当load失败时可以考虑加大MyQL网络包的配置:\nset global max_allowed_packet=max_var;"
    echo "----------------------------------"
    echo
    while :
    do
        type_[0]=`sed -n 's/<algorithm value=\(.*\)>/\1/gp' ${conf_file}|sed 's/>.*<!.*//g;s/\ //g'` #保存拆分算法
        if [ "${type_[0]}x" == "hashx" -o "${type_[0]}x" == "rangx" ]
        then
            echo >/dev/null
        else
            echo "<algorithm value=>配置错误，请改成hash或rang。" >${message_file};
            SendMessage
            continue
        fi
        type_[1]=`sed -n 's/<dn count=\(.*\)>/\1/gp' ${conf_file}|sed 's/>.*<!.*//g;s/\ //g'` #保存分片数
        expr ${type_[1]} + 0 >/dev/null 2<&1
        if [ $? -ne 0 ]
        then
            echo "dn标签count的配置有误，请改成数字。" >${message_file}
            SendMessage
            continue
        fi
        break
    done                    
    >${_dn_connect_info} #该文件存放各个分片的连接信息
    loop=1
    while ((${loop}<=${type_[1]})) 
    do
        #该循环验证配置文件中配置的分片的数据库相关的参数是否正确，若正确保存至${_dn_connect_info}
        type_[1]=`sed -n 's/<dn count=\(.*\)>/\1/gp' ${conf_file}|sed 's/>.*<!.*//g;s/\ //g'`
        sed -n 's/<!.*-->//g;s/<info>\(.*\)<.*$/\1/gp' ${conf_file} >${tmp_file}
        if [ "`wc -l <${tmp_file}`x" != "${type_[1]}x" ]
        then
            echo "dn标签count的值与info标签的个数不等，请修改。" >${message_file}
            #检查到配置文件配置存在错误，调用SendMessage函数向用户推送提示消息，提示用户更新配置文件
            SendMessage
            continue
        fi
        sed -i "s/\ //g;s/:/\ /g" ${tmp_file}
        [ -s ${tmp_file} ] && { info_=(`sed -n "${loop}p" ${tmp_file}`);}
        #-s 判断该文件是否为空，不为空info_=(`sed -n "${loop}p" ${tmp_file}`)。
        echo "---------------------------------"
        echo "第${loop}个分片的连接信息是:"
        echo -e "用户名：${info_[0]}\n密  码：${info_[1]}\n端口号：${info_[2]}\n主  机：${info_[3]}"
        #将下面这条SQL放在后台执行，并将pid保存在pid_select中，一秒后查看该pid是否还在，在表示这条sql没执行成功
        echo "select 1;"|mysql -u${info_[0]} -p${info_[1]} -P${info_[2]} -h${info_[3]} >/dev/null 2<&1 &
        if [ ${?} -eq 0 ]
        then
            echo "第${loop}个分片验证成功"
            [ "${loop}x" == "${type_[1]}x" ] && echo "---------------------------------"
            echo "mysql -u${info_[0]} -p${info_[1]} -P${info_[2]} -h${info_[3]}" >>${_dn_connect_info}
            let loop=$loop+1
        else
            echo "第${loop}个分片验证失败，请修改。" >${message_file}
            loop=1
            SendMessage
        fi
    done
    for ((dn_i=1;dn_i<=`wc -l < ${_dn_connect_info}`;dn_i++))
    do 
        tmp_dn_info=`sed -n "${dn_i}p" ${_dn_connect_info}`
        [ ${dn_i} -eq 1 ] && echo ${tmp_dn_info} >${dn_connect_info} && continue
        echo ${tmp_dn_info} > ${tmp_file}
        for ((dn_j=1;dn_j<=`wc -l < ${dn_connect_info}`;dn_j++))
        do
            cat ${dn_connect_info} >> ${tmp_file}
            if [ `sort -u ${tmp_file}|wc -l` -ne `wc -l < ${dn_connect_info}` ]
            then
                echo ${tmp_dn_info} >> ${dn_connect_info} 
                break
            fi
        done
    done
    [ `wc -l < ${dn_connect_info}` -gt 1 ] && global_multi_sharding=1 #大于1表示其本身就分片
    echo

    truncate_mark=`sed -n "s/<\!.*-->//g;s/<primary value=\(.*\)>/\1/gp" ${conf_file}|sed 's/\ //g'`

    if [ "$(sort ${_dn_connect_info}|uniq|wc -l)x" == "1x" ] && [ "$(wc -l < ${_dn_connect_info})x" != "1x" ] && [ "${truncate_mark}x" == "truex" ]
    then
        echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[31m<primary value=true>不能配置成true, 需要分片的情况下, 且所有分片都是同一个节点load数据之前不能清空表!!!\033[0m"
        exit 1
    fi

    echo "现在开始准备各分片的数据---"
    echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
    for loop in `seq ${type_[1]}`
    do
        error_file="${error_file_tmp}_${loop}.log"
        [ "${loop}x" != "1x" ] && sleep $((${loop}-1))
        while :
        do
            echo ${loop} > ${lock_file} 2>/dev/null && chattr +i ${lock_file} 2>/dev/null
            [ $? -eq 0 ] && break || sleep 1
        done
        old_id=`sed -n "s/<\!.*-->//g;s/<num>\(.*\)<\/num>.*/\1/gp" ${conf_file}|sed 's/ //g'`
        while : 
        do 
            row=`sed -n 's/<\!.*-->//g;s/<row max=.*>\(.*\)<\/row>.*/\1/gp' ${conf_file}`
            expr ${row} + 0 >/dev/null 2<&1
            if [ $? -ne 0 ]
            then
                echo "<row>标签的配置有误，请改成数字。" >${message_file}
                SendMessage
            else
                break
            fi
        done
        if [ "${type_[0]}x" == "hashx" ]
        then
            [ "${new_id}x" == "x" ] && new_id=${old_id} || new_id=$((${old_id}+1))
            sed -i "s/<step>\(.*\)<\//<step>${type_[1]}<\//g" ${conf_file}
        elif [ "${type_[0]}x" == "rangx" ]
        then
            new_id=$((${old_id}+${row}))
            sed -i "s/<step>\(.*\)<\//<step>1<\//g" ${conf_file}
        fi
        sed -i "s/<num>\(.*\)<\//<num>${new_id}<\//g" ${conf_file}
        cd ${program_dir}
        >${error_file}
        [ ! -x "${program_file}" ] && chmod +x ${program_file}
        ./${program_file} >${data_file}_${loop} 2>>${error_file} &
        pid_prepare="${!}"
	echo "${pid_prepare}" >> ${pid_tmp_file}
	[ "$(cat ${lock_file})x" == "${loop}x" ] && chattr -i ${lock_file} 2>/dev/null
	kill_pid_str="kill $(cat ${pid_tmp_file}|sed '/^$/d'|tr "\n" " ")"
	echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[35m开始准备第${loop}个分片的数据, 进程号为:${pid_prepare}, 如需终止请执行: ${kill_pid_str}\033[0m"
        lost_time=0
        while :
        do 
            count_prepare=`ps -ef|grep ${pid_prepare}|grep ${program_file}|grep -v grep|wc -l`
            sleep 1
            lost_time=$((${lost_time}+1))
            now_time="[$(date "+%F %H:%M:%S")]"
            #echo -ne "\033[32m"
            if [ ${count_prepare} -ne 0 ]
            then
                if [ "$(cat ${lock_file})x" == "${loop}x" ]
                then
                    printf "\033[32m%s \033[35m正在准备各分片的数据，现已用时 : \033[33m%ds\033[0m\r" "${now_time}" ${lost_time}
                fi
            else
                break
            fi
        done
        if [ ! -s "${error_file}" -a "$(head ${data_file}_${loop}|wc -l)x" != "0x" ]
        then
            if [ -f "${pid_tmp_file}" ]
            then
                sed -i "s/${pid_prepare} //g" ${pid_tmp_file}
                sed -i "s/${pid_prepare}//g" ${pid_tmp_file}
                kill_pid_str="kill $(cat ${pid_tmp_file}|sed '/^$/d'|tr "\n" " ")"
                if [ "${kill_pid_str}x" == "kill x" ]
                then
                    echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[35m第${loop}个分片的数据准备完成，各分片数据准备完成，总共用时 : \033[33m${lost_time}s\033[0m"
                else
                    echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[35m第${loop}个分片的数据准备完成，如需终止其他准备数据进程请执行: ${kill_pid_str}\033[0m"
                fi
            fi
        else
            echo -e "\033[31m第${loop}个分片的数据准备失败!!!\033[0m"
            echo "失败原因:`cat ${error_file}`"
            exit
	fi
	[ -f "${error_file}" ] && rm -f ${error_file}
    done
    [ -f "${pid_tmp_file}" ] && rm -f ${pid_tmp_file}
    echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
    sed -i "s/<num>\(.*\)<\//<num>0<\//g" ${conf_file} #每次生成完毕，将起始值置为0`
    cat ${_conf_file} > ${conf_file} #还原配置文件
    echo 
    echo "现在开始load各分片的数据---"
    echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"

    for loop in `seq ${type_[1]}`
    do
        error_file="${error_file_tmp}_${loop}.log"
        [ "${loop}x" != "1x" ] && sleep $((${loop}-1))
        load_comm="load DATA local INFILE '${data_file}_${loop}' INTO TABLE ${db_name}.${t_name} fields terminated by '${delimiter_str}';"
        [ ${choose} -eq 3 ] && cat ${create_info}|$(sed -n "${loop}p" ${dn_connect_info}) >/dev/numm 2<&1
        if [ "${truncate_mark}x" == "truex" ] 
        then
            echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[31mload数据之前清空该表!!!\033[0m"
            [ ${loop} -le `wc -l < ${dn_connect_info}` ] && echo "truncate ${db_name}.${t_name};"|$(sed -n "${loop}p" ${dn_connect_info}) >/dev/null 2<&1
            #为了预防主键冲突
        elif [ "${truncate_mark}x" == "falsex" ]
        then
            echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[31m第${loop}个分片, load数据之前不清空该表!!!\033[0m"
        else
            echo "\033[32m[$(date "+%F %H:%M:%S")] primary标签value的值配置错误，请修改。" >${message_file}
            SendMessage
        fi
        while :
        do
            [ "${loop}x" != "1x" ] && sleep $((${loop}-1))
            run_load="$(echo "show full processlist"|$(sed -n "${loop}p" ${_dn_connect_info}) 2>/dev/null|grep -c "load DATA local INFILE.*${db_name}\.${t_name}")"
            [ "${run_load}x" == "0x" ] && break || sleep 1
        done
        echo "${load_comm}"|$(sed -n "${loop}p" ${_dn_connect_info}) 2>>${error_file} &
        pid_load="${!}"
        echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[35m开始load第${loop}个分片, 进程号为:${pid_load}\033[0m"
        lost_time=0
        while :
        do 
            count_load=`ps -ef|grep ${pid_load}|grep mysql|grep -v grep |wc -l`
            sleep 1
            lost_time=$((${lost_time}+1))
            now_time="[$(date "+%F %H:%M:%S")]"
            [ ${count_load} -ne 0 ] && { printf "\033[32m%s \033[35m请耐心等待，现已用时:\033[33m%ds\033[0m\r" "${now_time}" ${lost_time};} || { echo ;break;}
        done
        state_load=`sed '/.*Using a password on the command line.*/d' ${error_file}|wc -l`
        dn_com="$(sed -n "${loop}p" ${_dn_connect_info})"
        check_data_true_sharding "${data_file}_${loop}" "第${loop}个分片"
        echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[35m第${loop}个分片, 验证结束\033[0m"
        if [ ${state_load} -eq 0 ]
        then
            if [ ${global_data_is_true} -eq 1 ]
            then
                echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[35m第${loop}个分片导入成功\033[0m"
                global_data_is_true=0
            else
                echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[31m第${loop}个分片导入数据量与生成的数据量不符,请前往数据库检查\033[0m"
            fi
        else
            echo -e "\033[32m[$(date "+%F %H:%M:%S")] \033[31m第${loop}个分片导入失败,失败原因如下!!!\033[0m"
            sed '/.*Using a password on the command line.*/d' ${error_file}
        fi
	[ -f "${error_file}" ] && rm -f ${error_file}
    done
    wait
    echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
    [ -f "${_dn_connect_info}" ] && rm -f ${_dn_connect_info}
    [ -f "${dn_connect_info}" ] && rm -f ${dn_connect_info}
    echo -ne "\033[33m请输入任意键返回主菜单，或输入q退出程序\033[0m:"
    read str
    [ "${str}x" == "qx" ] && { exit;}
    echo
    echo
    echo
}

function auto_get()
{
    public
    >${tmp_file}
    get_table_info
    cat ${tmp_file} | sed '1d' | awk '{print $2}' >${length_file}
    >${tmp_file}
    for i in `seq \`wc -l <${length_file}\``
    do
        sed -n ${i}p ${length_file} |sed 's/^date.*$/0/g;s/^time.*$/0/g;s/^text.*$/65535/g;s/^blob.*$/65535/g'|tr -d "a-zA-Z()" >>${tmp_file}
    done
    cat ${tmp_file} >${length_file}
    data_get
}

function enter_get()
{
       
    public
    echo -e "\033[31m${t_name}表的表结构如下\033[0m：" 
    >${tmp_file}
    get_table_info
    sed '1a----------------------' ${tmp_file}
    echo "----------------------"
    echo -e "\033[31m提示：如果数据类型是时间类型，请输入“0”，若是其他数据类型，输入具体数字,，此操作请谨慎！\033[0m"
    sed '1d' ${tmp_file}|awk '{print $2}'|sed  's/^date.*$/0/g;s/^time.*$/0/g'|tr -d "a-zA-Z()" > ${length_file}
    cat ${length_file} >${tmp_file}
    >${length_file}
    column=1
    max_column=`cat ${tmp_file}|wc -l`
    while :
    do
        num=`sed -n ${column}p ${tmp_file}`
        echo -en "请输入第${column}列的长度,\033[31m最大长度为-${num}-\033[0m:"
        read length
        [ "$length}x" == "0x" -a ${num} -gt 0 ] && echo -e "\033[31m输入错误,\033[0m请输入大于0的数！" && continue
        if [ -z "$(sed -n '/^[0-9][0-9]*$/p' <<< "${length}")" ]
        then
            echo -e "\033[31m输入错误,\033[0m请重新输入！"
            continue
        fi
        if [ ${length} -gt ${num} ]
        then
            echo -e "\033[31m输入有误，\033[0m超过该字段的最大长度，请重新输入!!!"
            continue
        fi
        if [ ! -n "${length}" ]
        then
            column=$((${column}-1))
        else	
            echo ${length} >> ${length_file}
        fi
        if [ "${column}x" == "${max_column}x" ]
        then
            break
        else
            column=$((${column}+1))
        fi
    done
    data_get
}

function sysbench_data()
{
    read -p "输入r返回上一层菜单,请输入库名(默认为“sbtest库”):" db_name
    [ -z ${db_name} ] && db_name=sbtest
    [ "${db_name}x" == "rx" ] && main_menu
    cat <<END >${create_info}
    Create Database If Not Exists ${db_name} Character Set UTF8;
    use ${db_name};
    CREATE TABLE If Not Exists sbtest1 (\
    id int(10) unsigned NOT NULL AUTO_INCREMENT,\
    k int(10) unsigned NOT NULL DEFAULT '0',\
    c char(120) NOT NULL DEFAULT '',\
    pad char(60) NOT NULL DEFAULT '',\
    PRIMARY KEY (id),   \
    KEY k_1 (k)\
    )ENGINE=InnoDB DEFAULT CHARSET=utf8 MAX_ROWS=1000000;
END
    echo -e "10\n10\n120\n60" >${length_file}
    t_name=sbtest1
    PRI_KEY_NAME=id
    PRI_KEY_ADDR=1
    auto_increment=1
    step=1
    sed -i "s/<addr>\(.*\)<\//<addr>${PRI_KEY_ADDR}<\//g;s/<num>\(.*\)<\//<num>${auto_increment}<\//g;s/<step>\(.*\)<\//<step>${step}<\//g" ${conf_file}
    data_get
}

function main_menu()
{
    info_connect   
    echo -e "请注意:\n该程序仅支持整型、字符型及时间类型的字段，\n如存在其他类型将可能导致未知的错误！！！"
    echo "请联系`cat ${work_path}/Help.txt`"
    echo "----------------------------------"  
    echo "0.结束运行。 "  
    echo "1.自动获取字段及各字段长度。"  
    echo "2.手动输入字段及各字段长度。"  
    echo "3.准备sysbench测试数据。"  
    echo "4.更改连接信息。"  
    echo -e "5.\033[31m编辑配置文件。\033[0m"  
    echo "----------------------------------"  
    read -p "请输入您的选择:" choose
    case ${choose} in  
        0)    
            exit;;  
        1)  
            auto_get
            ;;  
        2)  
            enter_get
            ;;
        3)
            sysbench_data
            ;;
        4)
            vim ${mysql_info}
            mysql_connect
            main_menu
            ;;
        5)
            echo  >${message_file}
            vim ${conf_file} +1
            main_menu
            ;;
        *)
            main_menu
            ;;
    esac  
}

mysql_connect
while :
do
    echo `tty` >${tty_file}
    sh ${program_dir}/SendMessage.sh ${tty_file} ${message_file} & >/dev/null 2<&1
    SendMessage_pid=$!
    main_menu
done
